#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/asm/gpio.h>

struct input_dev * buttons_dev;
static struct ping_desc * buttons_id;
static struct timer_list buttons_timer;

struct ping_desc
{
    unsigned char * name;
    int pin_irq;
    unsigned int pin;
    unsigned int irq_ctl;
    unsigned int button;
};

static strcut ping_desc buttons_desc[5] = {
    {"s1", IRQ_EINT0, GPF0, IRQ_TYPE_EDGE_BOTH, KEY_L},
    {"s2", IRQ_EINT1, GPF1, IRQ_TYPE_EDGE_BOTH, KEY_S},
    {"s3", IRQ_EINT2, GPF2, IRQ_TYPE_EDGE_BOTH, KEY_SPACE},
    {"s4", IRQ_EINT3, GPF3, IRQ_TYPE_EDGE_BOTH, KEY_ENTER},
};

void buttons_timer_function(unsigned long i)
{
    int val;

    val = gpio_getpin(buttons_id->pin);
    if (val) {
        input_event(buttons_dev, EV_KEY, buttons_id->button, 0); // not press
        input_sync(buttons_dev);
    }
    else {
        input_event(buttons_dev, EV_KEY, buttons_id->button, 1); // press
        input_sync(buttons_dev);
    }
}

static int buttons_init(void)
{
    int i;

    buttons_dev = input_allocate_device();
    set_bit(EV_KEY, buttons_dev->evbit);
    set_bit(EV_REP, buttons_dev->evbit);

    set_bit(KEY_L, buttons_dev->keybit);
    set_bit(KEY_S, buttons_dev->keybit);
    set_bit(KEY_SPACE, buttons_dev->keybit);
    set_bit(KEY_ENTER, buttons_dev->keybit);

    input_register_device(buttons_dev);

    init_timer(&buttons_timer);
    buttons_timer.function = buttons_timer_function;
    add_timer(&buttons_timer);

    for (i = 0; i < 4; i++) 
        request_irq(buttons_desc[i].pin_irq, buttons_irq, buttons_desc[i].irq_ctl,
                    buttons_desc[i].name, &buttons_desc[i]);

    return 0;
}

static int bottuons_exit(void)
{
    int i;

    for (i =0 ; i < 4; i++) 
        free_irq(buttons_desc[i].pin_irq, &buttons_desc[i]);

    del_timer(&buttons_timer);
    input_unregister_device(buttons_dev);
    input_free_device(buttons_dev);

    return 0;
}

module_init(buttons_init);
module_exit(buttons_exit);
MODULE_LICENSE("GPL v2");
